#include "stdafx.h"
#include "boundingbox.h"

#include <stdexcept>

namespace GLC {

BoundingBox::BoundingBox()
:_isEmpty(true)
{
}

BoundingBox::BoundingBox(vec3f const& minCoord, vec3f const& maxCoord)
:_isEmpty(false)
,_minCoord(minCoord)
,_maxCoord(maxCoord)
{
}

vec3f const & BoundingBox::getMinCoord() const
{
    if (_isEmpty)
    {
        throw std::logic_error("Bounding box is empty");
    }
    return _minCoord;
}

vec3f const & BoundingBox::getMaxCoord()const
{
    if (_isEmpty)
    {
        throw std::logic_error("Bounding box is empty");
    }
    return _maxCoord;
}

vec3f const BoundingBox::getSize()const
{
    if (_isEmpty)
    {
        return vec3f(0, 0, 0);
    }
    return _maxCoord - _minCoord;
}

vec3f const BoundingBox::getCenter()const
{
    if (_isEmpty)
    {
        throw std::logic_error("Bounding box is empty");
    }
    return (_minCoord + _maxCoord) * 0.5;
}

BoundingBox BoundingBox::getUnion(BoundingBox const& other)const
{
    if (_isEmpty && other._isEmpty) // both boxes are empty
    {
        return BoundingBox();
    }
    else if (_isEmpty) // this box is empty
    {
        return other;
    }
    else if (other._isEmpty) // another box is empty
    {
        return *this;
    }
    else	// both boxes aren't empty
    {
        using namespace std;
        return BoundingBox(
            vec3f(
                min(_minCoord.x, other._minCoord.x),
                min(_minCoord.y, other._minCoord.y),
                min(_minCoord.z, other._minCoord.z)
                ),
            vec3f(
                max(_maxCoord.x, other._maxCoord.x),
                max(_maxCoord.y, other._maxCoord.y),
                max(_maxCoord.z, other._maxCoord.z)
            )
        );
    }
}

bool BoundingBox::isEmpty() const
{
    return _isEmpty;
}

} // namespace GLC
